﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Utilities.cs" company="Roman '4ux-nbIx' Novitsky">
//   Copyright (c) 2012 Roman '4ux-nbIx' Novitsky
// </copyright>
// <summary>
//   Contains utility methods.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace MonoDevAssist
{
  #region Namespace Imports

  using System;
  using System.Diagnostics;
  using System.IO;

  using Microsoft.VisualStudio;
  using Microsoft.VisualStudio.Shell;
  using Microsoft.VisualStudio.Shell.Interop;

  #endregion


  /// <summary>
  /// Contains utility methods.
  /// </summary>
  internal static class Utilities
  {
    #region Constants and Fields

    private static bool _frameworkChecked;

    #endregion


    #region Public Methods

    public static void CheckMonoTouchFramework()
    {
      if (_frameworkChecked)
      {
        return;
      }

      var programFilesFolder = GetProgramFilesFolder();

      if (!CheckFrameworkRedistListFolder(programFilesFolder))
      {
        const string message =
          "MonoTouch Framework or one of it's components not installed: missing FrameworkList.xml. \n\nPlease follow the installation instructions at http://monodevassist.codeplex.com/";
        ShowMessageBox(message);
      }

      if (!CheckFrameworkAssembliesFolder(programFilesFolder))
      {
        const string message =
          "MonoTouch Framework or one of it's components not installed: missing framework assemblies. \n\nPlease follow the installation instructions at http://monodevassist.codeplex.com/";
        ShowMessageBox(message);
      }

      if (!CheckMsBuildTargetsFile(programFilesFolder))
      {
        const string message =
          "MonoTouch Framework or one of it's components not installed: missing MSBuild targets file. \n\nPlease follow the installation instructions at http://monodevassist.codeplex.com/";
        ShowMessageBox(message);
      }

      _frameworkChecked = true;
    }


    public static void ShowMessageBox(string message)
    {
      // Show a Message Box to prove we were here
      var uiShell = (IVsUIShell)Package.GetGlobalService(typeof(SVsUIShell));
      Guid clsid = Guid.Empty;
      int result;
      ErrorHandler.ThrowOnFailure(
        uiShell.ShowMessageBox(
          0, 
          ref clsid, 
          "MonoDevAssist", 
          message, 
          string.Empty, 
          0, 
          OLEMSGBUTTON.OLEMSGBUTTON_OK, 
          OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST, 
          OLEMSGICON.OLEMSGICON_CRITICAL, 
          0, 
          out result));
    }

    #endregion


    #region Methods

    private static bool CheckFrameworkAssembliesFolder(string programFilesFolder)
    {
      var frameworkPath = Path.Combine(programFilesFolder, @"Reference Assemblies\Microsoft\Framework\MonoTouch\v1.0");

      if (!Directory.Exists(frameworkPath))
      {
        return false;
      }

      return Directory.GetFiles(frameworkPath).Length != 0;
    }


    private static bool CheckFrameworkRedistListFolder(string programFilesFolder)
    {
      return TryCreateFile(
        programFilesFolder, 
        @"Reference Assemblies\Microsoft\Framework\MonoTouch\v1.0\RedistList\", 
        @"FrameworkList.xml", 
        "MonoDevAssist.Resources.FrameworkList.xml");
    }


    private static bool CheckMsBuildTargetsFile(string programFilesFolder)
    {
      return TryCreateFile(
        programFilesFolder, 
        @"MSBuild\MonoTouch\", 
        @"Novell.MonoTouch.Common.targets", 
        "MonoDevAssist.Resources.MonoTouch.targets");
    }


    private static string GetProgramFilesFolder()
    {
      var programFilesFolder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);

      if (!Directory.Exists(programFilesFolder))
      {
        programFilesFolder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
      }

      return programFilesFolder;
    }


    private static bool TryCreateFile(
      string programFilesFolder, string relativeFolderPath, string fileName, string embeddedResourceName)
    {
      var basePath = Path.Combine(programFilesFolder, relativeFolderPath);
      var targetsFilesPath = Path.Combine(basePath, fileName);

      if (!File.Exists(targetsFilesPath))
      {
        FileStream stream = null;
        Stream sourceStream = null;

        try
        {
          Directory.CreateDirectory(basePath);

          string targetsFileContent;

          sourceStream = typeof(MonoTouchFlavePackageProject).Assembly.GetManifestResourceStream(embeddedResourceName);

          Debug.Assert(sourceStream != null, "Failed to open embedded resource.");

          using (var reader = new StreamReader(sourceStream))
          {
            sourceStream = null;

            targetsFileContent = reader.ReadToEnd();
          }

          stream = new FileStream(targetsFilesPath, FileMode.CreateNew, FileAccess.Write);

          using (var writer = new StreamWriter(stream))
          {
            stream = null;

            writer.Write(targetsFileContent);
          }
        }
        catch
        {
          return false;
        }
        finally
        {
          if (stream != null)
          {
            stream.Dispose();
          }

          if (sourceStream != null)
          {
            sourceStream.Dispose();
          }
        }
      }

      return true;
    }

    #endregion
  }
}